package Sync;


import Sync.Tool.CreatFiles;
import Sync.Tool.SyncTool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.SocketException;
import java.util.List;

public class SyncReceiveThread extends Thread{
    private static final Logger log = LoggerFactory.getLogger(SyncReceiveThread.class);
    private final SharedSocket sharedSocket;
    private final InteractiveLogic RInteractiveLogic;


    public SyncReceiveThread(SharedSocket sharedSocket, InteractiveLogic interactiveLogic)  {
        this.sharedSocket =  sharedSocket;
        this.RInteractiveLogic = interactiveLogic;
        this.sharedSocket.increment();
    }
    // 在 SyncReceiveThread 中添加


    @Override
    public void run(){
        System.out.println("SyncReceiveThread启动...");
        //传入key值，必须跟手机端是统一的！！！
        DirsData dirsData = new DirsData(new File( "E:\\testAPK"), "云同步根目录");

        try {
            //只要存在目录，就一直循环
            while(!dirsData.isDirsEmpty()) {


                DataInputStream dis = new DataInputStream(sharedSocket.getInputStream());
                String InteractiveLogicJson = dis.readUTF();
                //解析和处理交互逻辑对象
                InteractiveLogic interactiveLogic = parseInteractiveLogicFromString(InteractiveLogicJson);
                //获取目录
                File dir =dirsData.pollDirByKey(interactiveLogic.getSyncingFolder());
                processFileSyncComparison(interactiveLogic, dir);

                //TODO: 对编辑时间旧旧的文件进行保存
                //TODO:创建跟手机端相同的子文件夹目录
                //TODO:跟踪同步日志

                //添加云同步目录所有子文件夹
                if(interactiveLogic.getIsFistSync()){
                    List<String> pcDirs = CreatFiles.getAllSubdirectoriesRelativePaths(dir);
                    List<String> NewSubDirsToPhone = CreatFiles.processFolderSync(pcDirs, interactiveLogic.getSubDirs_phone(), dir);
                    interactiveLogic.setNewSubDirsToPhone(NewSubDirsToPhone);
                    dirsData.addMapToDirs(dirsData.collectAllDirectoriesRecursively(dir, "NoRootDirName"));
                }
                interactiveLogic.clearPhoneFileDetailsAndSaveSyncPC();
                //拷贝对象
                RInteractiveLogic.copyFrom(interactiveLogic);
                //唤醒发送线程
                sharedSocket.notifySend();

                //如果手机端发送文件数量大于0，接受手机端发送的文件内容同步
                if (interactiveLogic.getFileContentSync_Count() > 0) {
                    int syncSum = interactiveLogic.getFileContentSync_Count();
                    for (int i = 1; i <= syncSum; i++) {
                        receiveFile(dis, dir);
                    }

                }

                //如果手机端发送新增文件大于0，接受手机端发送的文件保存同步
                if (interactiveLogic.getFileAdditionSync_Count() > 0) {
                    int syncSum = interactiveLogic.getFileAdditionSync_Count();
                    for (int i = 1; i <= syncSum; i++) {
                        receiveFile(dis, dir);
                    }

                }
            }
            //TODO :结束发送线程的循环
            sharedSocket.setShouldStopSending(true);
            sharedSocket.decrement();
            log.info("接收线程正常结束：所有文件已同步");


        } catch (EOFException ignored) {
            log.debug("接收线程正常结束：客户端已关闭连接");
        } catch (SocketException e) {
            if (e.getMessage().contains("Socket closed")) {
                log.debug("接收线程正常结束：套接字已关闭");
            } else {
                log.error("网络传输异常：{}", e.getMessage(), e);
            }
        } catch (IOException e) {
            log.error("网络传输异常：{}", e.getMessage(), e);
        } catch (Exception e) {
            log.error("处理异常：{}", e.getMessage(), e);
        }

    }
    /**
     * 从输入流接收文件并保存到指定路径
     * @param dis 数据输入流
     * @throws IOException 当发生IO异常时抛出
     */
    private void receiveFile(DataInputStream dis,File  dir) throws IOException {
        String fileName = dis.readUTF();
        long fileLength = dis.readLong();
        log.info("文件名：" + fileName + "文件大小：" + fileLength);

        
        File file = new File(dir, fileName);
        // 覆盖已存在的文件
        try (FileOutputStream fos = new FileOutputStream(file, false)) {

            byte[] buffer = new byte[8192];
            long receivedBytes = 0;
            while (receivedBytes < fileLength) {
                int read = dis.read(buffer, 0, Math.min(buffer.length, (int) (fileLength - receivedBytes)));
                if (read == -1) break;
                fos.write(buffer, 0, read);
                receivedBytes += read;

            }
        }
    }


    /**
     * 解析JSON字符串为InteractiveLogic对象
     * @param interactiveLogicJson 包含InteractiveLogic对象信息的JSON字符串
     * @return 解析后的InteractiveLogic对象
     */
    private InteractiveLogic parseInteractiveLogicFromString(String interactiveLogicJson) {

        InteractiveLogic interactiveLogic = SyncTool.fromJson(interactiveLogicJson);
        log.info("手机端文件夹所有文件信息getPhoneFileDetailsList" + interactiveLogic.getPhoneFileDetailsList());




        return interactiveLogic;
    }

    /**
     * 处理文件同步比较逻辑
     * @param interactiveLogic 交互逻辑对象
     * @param dir 目录文件
     */
    private void processFileSyncComparison(InteractiveLogic interactiveLogic, File dir) {
        List<File> fileList = SyncTool.listFilesInDirectory(dir);
        log.info("电脑端文件夹所有文件信息fileList: " + fileList);
        interactiveLogic.compareAndCategorizeFiles(fileList, interactiveLogic.getPhoneFileDetailsList());
        log.info("电脑端要发送内容同步文件数量"+interactiveLogic.getFileContentSync_PC_Count() );
        log.info("电脑端要进行发送内容同步的文件getFileContentSync_PC"+interactiveLogic.getFileContentSync_PC().toString() );
        log.info("电脑端要保存编辑时间较旧的的文件getFileSaveSync_PC"+interactiveLogic.getFileSaveSync_PC().toString() );

        log.info("手机端要发送的文件数量"+interactiveLogic.getFileContentSync_Count());
        log.info("手机端要进行发送内容同步的文件"+interactiveLogic.getFileContentSync().toString());
        log.info("手机端要保存编辑时间较旧的的文件"+interactiveLogic.getFileSaveSync().toString());

        interactiveLogic.findNonIntersectingFiles(fileList, interactiveLogic.getPhoneFileDetailsList());
        log.info("电脑端新增要发送文件数量" + interactiveLogic.getFileAdditionSync_PC().size());
        log.info("电脑端新增要发送文件："+interactiveLogic.getFileAdditionSync_PC().toString() );
        log.info("手机端新增要发送文件数量"+interactiveLogic.getFileAdditionSync().size() );
        log.info("手机端新增要发送文件："+interactiveLogic.getFileAdditionSync().toString() );

    }



}